home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Utilities / MView / gxu / crackdecl.h < prev    next >
Encoding:
C/C++ Source or Header  |  2004-09-27  |  25.5 KB  |  732 lines

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. //  Copyright (C) 2000 Microsoft Corporation.  All Rights Reserved.
  4. //
  5. //  File:       crackdecl.h
  6. //  Content:    Used to access vertex data using Declarations or FVFs
  7. //
  8. //////////////////////////////////////////////////////////////////////////////
  9.  
  10. #pragma once
  11.  
  12. #ifndef __CRACKDECL_H__
  13. #define __CRACKDECL_H__
  14.  
  15. #include <d3dx9.h>
  16.  
  17. //----------------------------------------------------------------------------
  18. // CD3DXCrackDecl
  19. //----------------------------------------------------------------------------
  20.  
  21. class CD3DXCrackDecl
  22. {
  23. protected:
  24.     
  25.     //just a pointer to the Decl! No data stored!
  26.     CONST D3DVERTEXELEMENT9 *pElements;
  27.     DWORD dwNumElements;
  28.  
  29.     //still need the stream pointer though
  30.     //and the strides
  31.     LPBYTE pStream[16];
  32.     DWORD  dwStride[16];
  33.  
  34. public:
  35.  
  36.     CD3DXCrackDecl();
  37.    
  38.  
  39.     HRESULT SetDeclaration( CONST D3DVERTEXELEMENT9 *pDecl);
  40.     HRESULT SetStreamSource(UINT Stream, LPVOID pData,UINT Stride);
  41.  
  42.     // Get
  43.     inline UINT GetVertexStride(UINT Stream);
  44.  
  45.     
  46.     inline UINT GetFields(CONST D3DVERTEXELEMENT9*);
  47.  
  48.     inline LPBYTE GetVertex(UINT Stream,  UINT Index);
  49.     inline LPBYTE GetElementPointer(CONST D3DVERTEXELEMENT9 *Element,UINT Index);
  50.  
  51.  
  52.     inline CONST D3DVERTEXELEMENT9 *GetSemanticElement(UINT Usage,UINT UsageIndex);
  53.     //simple function that gives part of the decl back 
  54.     inline CONST D3DVERTEXELEMENT9 *GetIndexElement(UINT Index);
  55.  
  56.     // Encode/Decode
  57.     VOID Decode(CONST D3DVERTEXELEMENT9 *, UINT Index, FLOAT* pData, UINT cData);
  58.     VOID Encode(CONST D3DVERTEXELEMENT9 *, UINT Index, CONST FLOAT* pData, UINT cData);
  59.  
  60.     inline VOID DecodeSemantic(UINT Usage,UINT UsageIndex,UINT VertexIndex, FLOAT *pData,UINT cData);
  61.     inline VOID EncodeSemantic(UINT Usage,UINT UsageIndex,UINT VertexIndex, FLOAT *pData,UINT cData);
  62.  
  63.     inline CONST D3DVERTEXELEMENT9 *GetElements() { return pElements; };
  64.     inline DWORD GetNumElements() { return dwNumElements; };
  65. };
  66.  
  67.  
  68. //----------------------------------------------------------------------------
  69. // CD3DXCrackDecl inline methods
  70. //----------------------------------------------------------------------------
  71. inline CONST D3DVERTEXELEMENT9*
  72. CD3DXCrackDecl::GetIndexElement(UINT Index)
  73. {
  74.     if(Index < dwNumElements)
  75.         return &pElements[Index];
  76.     else
  77.         return NULL;
  78. }
  79.  
  80. inline CONST D3DVERTEXELEMENT9*
  81. CD3DXCrackDecl::GetSemanticElement(UINT Usage,UINT UsageIndex)
  82. {
  83.     CONST D3DVERTEXELEMENT9 *pPlace = pElements;
  84.     while(pPlace->Stream != 0xFF)
  85.     {
  86.         if(pPlace->Usage == Usage &&
  87.            pPlace->UsageIndex == UsageIndex)
  88.            return pPlace;
  89.         pPlace++;
  90.     }
  91.     return NULL;
  92. }
  93.  
  94. inline VOID 
  95. CD3DXCrackDecl::DecodeSemantic(UINT Usage,UINT UsageIndex,UINT VertexIndex, FLOAT *pData,UINT cData)
  96. {
  97.     Decode(GetSemanticElement(Usage,UsageIndex),VertexIndex,pData,cData);
  98. }
  99.  
  100. inline VOID 
  101. CD3DXCrackDecl::EncodeSemantic(UINT Usage,UINT UsageIndex,UINT VertexIndex, FLOAT *pData,UINT cData)
  102. {
  103.     Encode(GetSemanticElement(Usage,UsageIndex),VertexIndex,pData,cData);
  104. }
  105.  
  106.  
  107. inline UINT 
  108. CD3DXCrackDecl::GetVertexStride(UINT Stream)
  109. {
  110.     return dwStride[Stream];
  111. }
  112.  
  113. const BYTE x_rgcbFields[] = 
  114. {
  115.     1, // D3DDECLTYPE_FLOAT1,        // 1D float expanded to (value, 0., 0., 1.)
  116.     2, // D3DDECLTYPE_FLOAT2,        // 2D float expanded to (value, value, 0., 1.)
  117.     3, // D3DDECLTYPE_FLOAT3,       / 3D float expanded to (value, value, value, 1.)
  118.     4, // D3DDECLTYPE_FLOAT4,       / 4D float
  119.     4, // D3DDECLTYPE_D3DCOLOR,      // 4D packed unsigned bytes mapped to 0. to 1. range
  120.     //                      // Input is in D3DCOLOR format (ARGB) expanded to (R, G, B, A)
  121.     4, // D3DDECLTYPE_UBYTE4,        // 4D unsigned byte
  122.     2, // D3DDECLTYPE_SHORT2,        // 2D signed short expanded to (value, value, 0., 1.)
  123.     4, // D3DDECLTYPE_SHORT4         // 4D signed short
  124.  
  125.     4, // D3DDECLTYPE_UBYTE4N,       // Each of 4 bytes is normalized by dividing to 255.0
  126.     2, // D3DDECLTYPE_SHORT2N,       // 2D signed short normalized (v[0]/32767.0,v[1]/32767.0,0,1)
  127.     4, // D3DDECLTYPE_SHORT4N,       // 4D signed short normalized (v[0]/32767.0,v[1]/32767.0,v[2]/32767.0,v[3]/32767.0)
  128.     2, // D3DDECLTYPE_USHORT2N,      // 2D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,0,1)
  129.     4, // D3DDECLTYPE_USHORT4N,      // 4D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,v[2]/65535.0,v[3]/65535.0)
  130.     3, // D3DDECLTYPE_UDEC3,         // 3D unsigned 10 10 10 format expanded to (value, value, value, 1)
  131.     3, // D3DDECLTYPE_DEC3N,         // 3D signed 10 10 10 format normalized and expanded to (v[0]/511.0, v[1]/511.0, v[2]/511.0, 1)
  132.     2, // D3DDECLTYPE_FLOAT16_2,     // 2D 16 bit float expanded to (value, value, 0, 1 )
  133.     4, // D3DDECLTYPE_FLOAT16_4,     // 4D 16 bit float 
  134.     0, // D3DDECLTYPE_UNKNOWN,       // Unknown
  135. };
  136.  
  137.  
  138. inline UINT 
  139. CD3DXCrackDecl::GetFields(CONST D3DVERTEXELEMENT9 *pElement)
  140. {
  141.     if(pElement->Type <= D3DDECLTYPE_FLOAT16_4)
  142.         return x_rgcbFields[pElement->Type];
  143.  
  144.     return 0;
  145. }
  146.  
  147.  
  148.  
  149. inline LPBYTE 
  150. CD3DXCrackDecl::GetVertex(UINT Stream, UINT Index)
  151. {
  152.     return pStream[Stream] + dwStride[Stream] * Index;
  153. }
  154.  
  155.  
  156. inline LPBYTE 
  157. CD3DXCrackDecl::GetElementPointer(CONST D3DVERTEXELEMENT9 *pElement, UINT Index)
  158. {
  159.     return GetVertex(pElement->Stream, Index) + pElement->Offset;
  160. }
  161.  
  162.  
  163. //----------------------------------------------------------------------------
  164. // CD3DXCrackDecl1 - Single stream enhanced crackdecl (combine CrackFVF and CrackDecl
  165. //----------------------------------------------------------------------------
  166.  
  167. class CD3DXCrackDecl1 : public CD3DXCrackDecl
  168. {
  169. public:
  170.     
  171.     CONST D3DVERTEXELEMENT9 *pPositionElement;
  172.     CONST D3DVERTEXELEMENT9 *pWeightElement;
  173.     CONST D3DVERTEXELEMENT9 *pIndexElement;
  174.     CONST D3DVERTEXELEMENT9 *pNormalElement;
  175.     CONST D3DVERTEXELEMENT9 *pDiffuseElement;
  176.     CONST D3DVERTEXELEMENT9 *pSpecularElement;
  177.  
  178.     CONST D3DVERTEXELEMENT9 *rgpTextureElements[8];
  179.  
  180.     DWORD m_cBytesPerVertex;
  181.  
  182.     BOOL BPosition()                                 { return pPositionElement != NULL; }
  183.     BOOL BWeights()                                  { return pWeightElement != NULL; }
  184.     BOOL BIndexedWeights()                           { return pIndexElement != NULL; }
  185.     BOOL BNormal()                                   { return pNormalElement != NULL; }
  186.     BOOL BDiffuse()                                  { return pDiffuseElement != NULL; }
  187.     BOOL BSpecular()                                 { return pSpecularElement != NULL; }
  188.     BOOL BTexCoord(UINT iTexCoord)                   { return rgpTextureElements[iTexCoord] != NULL; }
  189.                                                  
  190.     BOOL CWeights()                                  { return pWeightElement == NULL ? 0 : (pWeightElement->Type - D3DDECLTYPE_FLOAT1) + 1; }
  191.  
  192.     LPD3DXVECTOR3 PvGetPosition(PBYTE pvPoint)       { return (LPD3DXVECTOR3)(pvPoint + pPositionElement->Offset); }
  193.     LPD3DXVECTOR3 PvGetNormal(PBYTE pvPoint)         { return (LPD3DXVECTOR3)(pvPoint + pNormalElement->Offset); }
  194.     FLOAT *PfGetWeights(PBYTE pvPoint)               { return (FLOAT*)(pvPoint + pWeightElement->Offset); }
  195.     LPDWORD PdwGetIndices(PBYTE pvPoint)             { return (LPDWORD)(pvPoint + pIndexElement->Offset); }
  196.     FLOAT FGetWeight(PBYTE pvPoint, UINT iWeight)    { return ((FLOAT*)(pvPoint + pWeightElement->Offset))[iWeight]; }
  197.     LPD3DXVECTOR2 PuvGetTex1(PBYTE pvPoint)          { return (LPD3DXVECTOR2)(pvPoint + rgpTextureElements[0]->Offset); }
  198.  
  199.     void ColorGetDiffuse(PBYTE pvPoint, LPD3DXCOLOR pColor)
  200.     {
  201.         if (pDiffuseElement->Type == D3DDECLTYPE_D3DCOLOR)
  202.         {
  203.             *pColor = D3DXCOLOR(*(D3DCOLOR*)(pvPoint + pDiffuseElement->Offset));
  204.         }
  205.         else
  206.         {
  207.             *pColor = *(LPD3DXCOLOR)(pvPoint + pDiffuseElement->Offset);
  208.         }
  209.     }
  210.  
  211.     void ColorGetSpecular(PBYTE pvPoint, LPD3DXCOLOR pColor)
  212.     {
  213.         if (pSpecularElement->Type == D3DDECLTYPE_D3DCOLOR)
  214.         {
  215.             *pColor = D3DXCOLOR(*(D3DCOLOR*)(pvPoint + pSpecularElement->Offset));
  216.         }
  217.         else
  218.         {
  219.             *pColor = *(LPD3DXCOLOR)(pvPoint + pSpecularElement->Offset);
  220.         }
  221.     }
  222.  
  223.     PBYTE GetArrayElem(PBYTE pvPoints, UINT iVertex) { return pvPoints + m_cBytesPerVertex * iVertex; }
  224.  
  225.     void SetNormal(PBYTE pvPoint, LPD3DXVECTOR3 pvNormal)
  226.     {
  227.         if (pNormalElement != NULL)
  228.         {
  229.             *(LPD3DXVECTOR3)(pvPoint + pNormalElement->Offset) = *pvNormal;
  230.         }
  231.     }
  232.  
  233.     // no check set position
  234.     void SetPositionN(PBYTE pvPoint, LPD3DXVECTOR3 pvNormal)
  235.     {
  236.         *(LPD3DXVECTOR3)(pvPoint + pPositionElement->Offset) = *pvNormal;
  237.     }
  238.     // no check set normal
  239.     void SetNormalN(PBYTE pvPoint, LPD3DXVECTOR3 pvNormal)
  240.     {
  241.         *(LPD3DXVECTOR3)(pvPoint + pNormalElement->Offset) = *pvNormal;
  242.     }
  243.  
  244.     CD3DXCrackDecl1()
  245.         :CD3DXCrackDecl(),
  246.          pPositionElement(NULL),
  247.          pWeightElement(NULL),
  248.          pIndexElement(NULL),
  249.          pNormalElement(NULL),
  250.          pDiffuseElement(NULL),
  251.          pSpecularElement(NULL)
  252.         {
  253.         memset(rgpTextureElements, 0, sizeof(LPD3DVERTEXELEMENT9) * 8);
  254.         }
  255.   
  256.     CD3DXCrackDecl1(CONST D3DVERTEXELEMENT9 *pElementsNew)
  257.         :CD3DXCrackDecl(),
  258.          pPositionElement(NULL),
  259.          pWeightElement(NULL),
  260.          pIndexElement(NULL),
  261.          pNormalElement(NULL),
  262.          pDiffuseElement(NULL),
  263.          pSpecularElement(NULL)
  264.     {
  265.         memset(rgpTextureElements, 0, sizeof(LPD3DVERTEXELEMENT9) * 8);
  266.         SetDeclaration(pElementsNew);
  267.     }
  268.  
  269.     HRESULT SetDeclaration(CONST D3DVERTEXELEMENT9 *pElementsNew)
  270.     {
  271.         CONST D3DVERTEXELEMENT9 *pPlace;
  272.  
  273.         CD3DXCrackDecl::SetDeclaration(pElementsNew);
  274.  
  275. #ifdef DEBUG
  276.         // this class only works for single stream data types
  277.         pPlace = pElementsNew;
  278.         while(pPlace->Stream != 0xFF)
  279.         {
  280.             GXASSERT(pPlace->Stream == 0);
  281.             pPlace++;
  282.         }
  283. #endif
  284.         // should be pointing into local copy of declaration
  285.         pPlace = pElements;
  286.  
  287.         while(pPlace->Stream != 0xFF)
  288.         {
  289.             if (pPlace->UsageIndex == 0 || pPlace->Usage == D3DDECLUSAGE_TEXCOORD || 
  290.                 pPlace->Usage == D3DDECLUSAGE_COLOR )
  291.             {
  292.                 switch (pPlace->Usage)
  293.                 {
  294.                 case D3DDECLUSAGE_POSITION:
  295.                     if (pPlace->Type == D3DDECLTYPE_FLOAT3)
  296.                     {
  297.                         pPositionElement = pPlace;
  298.                     }
  299.                     break;
  300.  
  301.                 case D3DDECLUSAGE_BLENDWEIGHT:
  302.                     if ((pPlace->Type >= D3DDECLTYPE_FLOAT1) && (pPlace->Type <= D3DDECLTYPE_FLOAT4))
  303.                     {
  304.                         pWeightElement = pPlace;
  305.                     }
  306.                     break;
  307.  
  308.                 case D3DDECLUSAGE_BLENDINDICES:
  309.                     if ((pPlace->Type == D3DDECLTYPE_UBYTE4) || (pPlace->Type == D3DDECLTYPE_D3DCOLOR))
  310.                     {
  311.                         pIndexElement = pPlace;
  312.                     }
  313.                     break;
  314.  
  315.                 case D3DDECLUSAGE_NORMAL:
  316.                     if (pPlace->Type == D3DDECLTYPE_FLOAT3)
  317.                     {
  318.                         pNormalElement = pPlace;
  319.                     }
  320.                     break;
  321.  
  322.                 case D3DDECLUSAGE_COLOR:
  323.                     if (pPlace->UsageIndex == 0)
  324.                     {
  325.                         if ((pPlace->Type == D3DDECLTYPE_FLOAT4) || (pPlace->Type == D3DDECLTYPE_D3DCOLOR))
  326.                         {
  327.                             pDiffuseElement = pPlace;
  328.                         }
  329.                     }
  330.                     else
  331.                     if (pPlace->UsageIndex == 1)
  332.                     {
  333.                         if ((pPlace->Type == D3DDECLTYPE_FLOAT4) || (pPlace->Type == D3DDECLTYPE_D3DCOLOR))
  334.                         {
  335.                             pSpecularElement = pPlace;
  336.                         }
  337.                     }
  338.                     break;
  339.  
  340.                 case D3DDECLUSAGE_TEXCOORD:
  341.                     if ((pPlace->Type >= D3DDECLTYPE_FLOAT1) && (pPlace->Type <= D3DDECLTYPE_FLOAT4) && (pPlace->UsageIndex < 8))
  342.                     {
  343.                         rgpTextureElements[pPlace->UsageIndex] = pPlace;
  344.                     }
  345.                     break;
  346.                 }
  347.             }
  348.  
  349.             pPlace++;
  350.         }
  351.  
  352.         m_cBytesPerVertex = D3DXGetDeclVertexSize(pElements,0);
  353.  
  354.         return S_OK;
  355.     }
  356.  
  357.  
  358. };
  359.  
  360. //----------------------------------------------------------------------------
  361. // Very Useful decl functions!!
  362. //----------------------------------------------------------------------------
  363. // 
  364.  
  365. // struct used to contain state for cross fvf vertex copies
  366. struct SVertexCopyContext
  367. {
  368.     CD3DXCrackDecl1 cdSrc;
  369.     CD3DXCrackDecl1 cdDest;
  370.  
  371.     DWORD cDeclsToCopy;
  372.     CONST D3DVERTEXELEMENT9 *rgpCopyDeclSrc[MAX_FVF_DECL_SIZE];
  373.     CONST D3DVERTEXELEMENT9 *rgpCopyDeclDest[MAX_FVF_DECL_SIZE];
  374.  
  375.     // setup info required for fvf conversion
  376.     SVertexCopyContext(CONST D3DVERTEXELEMENT9 *pDeclSrc, CONST D3DVERTEXELEMENT9 *pDeclDest)
  377.         :cdSrc(pDeclSrc), cdDest(pDeclDest), cDeclsToCopy(0)
  378.     {
  379.         CONST D3DVERTEXELEMENT9 *pPlace = pDeclSrc;
  380.         CONST D3DVERTEXELEMENT9 *pDecl;
  381.  
  382.         // look through all the source decls
  383.         while(pPlace->Stream != 0xFF)
  384.         {
  385.             // see if there is a destination decl that matches this ones usage
  386.             pDecl = cdDest.GetSemanticElement(pPlace->Usage, pPlace->UsageIndex);
  387.  
  388.             // if one was found, save off the pair of vertex elements to copy between
  389.             //      NOTE: the type may not match, but encode and decode will make that work out
  390.             // D3DDECLMETHOD_UV is fantom data - it has no input, just output
  391.             if ((pDecl != NULL) && (pPlace->Method != D3DDECLMETHOD_UV) && (pDecl->Method != D3DDECLMETHOD_UV))
  392.             {
  393.                 rgpCopyDeclSrc[cDeclsToCopy] = pPlace;
  394.                 rgpCopyDeclDest[cDeclsToCopy] = pDecl;
  395.                 cDeclsToCopy += 1;
  396.             }
  397.  
  398.             pPlace++;
  399.         }
  400.     }
  401.  
  402.     void SetStreamSource(PBYTE pbSrc, PBYTE pbDest)
  403.     {
  404.         cdSrc.SetStreamSource(0, pbSrc, 0);
  405.         cdDest.SetStreamSource(0, pbDest, 0);
  406.     }
  407.  
  408.     // copy a vertex doing the fvf conversion in the process
  409.     void CopyVertex(UINT iVertSrc, UINT iVertDest, BOOL bInit)
  410.     {
  411.         DWORD iDecl;
  412.         FLOAT rgfTemp[4];
  413.         UINT iWeight;
  414.         UINT cWeights;
  415.         FLOAT fSum;
  416.  
  417.         // some usages may already have initialized other vertex elements
  418.         if (bInit)
  419.         {
  420.             memset(cdDest.GetVertex(0, iVertDest), 0, cdDest.m_cBytesPerVertex);
  421.         }
  422.  
  423.         for (iDecl = 0; iDecl < cDeclsToCopy; iDecl++)
  424.         {
  425.             cdSrc.Decode(rgpCopyDeclSrc[iDecl], iVertSrc, rgfTemp, 4);
  426.  
  427.             // special case blend weights, need to generate implied weight
  428.             if (rgpCopyDeclSrc[iDecl]->Usage == D3DDECLUSAGE_BLENDWEIGHT)
  429.             {
  430.                 // UNDONE UNDONE - is there any way to handle other datatypes in this case?
  431.  
  432.  
  433.                 // NOTE: it is valid to bypass this in the case of FLOAT4!!! there is no implied weight then
  434.                 if ((rgpCopyDeclSrc[iDecl]->Type >= D3DDECLTYPE_FLOAT1) && (rgpCopyDeclSrc[iDecl]->Type <= D3DDECLTYPE_FLOAT3))
  435.                 {
  436.                     cWeights = (rgpCopyDeclSrc[iDecl]->Type - D3DDECLTYPE_FLOAT1) + 1;
  437.  
  438.                     // calculate the sum of the specified weights
  439.                     fSum = 0.0f;
  440.                     for (iWeight = 0; iWeight < cWeights; iWeight++)
  441.                     {
  442.                         fSum += rgfTemp[iWeight];
  443.                     }
  444.  
  445.                     GXASSERT((cWeights > 0) && cWeights <= 3);
  446.  
  447.                     // set the implied weight
  448.                     rgfTemp[cWeights] = 1.0f - fSum;
  449.                 }
  450.             }
  451.  
  452.             cdDest.Encode(rgpCopyDeclDest[iDecl], iVertDest, rgfTemp, 4);
  453.         }
  454.     }
  455. };
  456.  
  457. inline BOOL BIdenticalDecls(CONST D3DVERTEXELEMENT9 *pDecl1, CONST D3DVERTEXELEMENT9 *pDecl2)
  458. {
  459.     CONST D3DVERTEXELEMENT9 *pCurSrc = pDecl1;
  460.     CONST D3DVERTEXELEMENT9 *pCurDest = pDecl2;
  461.     while ((pCurSrc->Stream != 0xff) && (pCurDest->Stream != 0xff))
  462.     {
  463. //        if (memcmp(pCurSrc, pCurDest, sizeof(D3DVERTEXELEMENT9)) != 0)
  464. //            break;
  465.         if ((pCurDest->Stream != pCurSrc->Stream) 
  466.             && (pCurDest->Offset != pCurSrc->Offset) 
  467.             || (pCurDest->Type != pCurSrc->Type) 
  468.             || (pCurDest->Method != pCurSrc->Method) 
  469.             || (pCurDest->Usage != pCurSrc->Usage) 
  470.             || (pCurDest->UsageIndex != pCurSrc->UsageIndex))
  471.             break;
  472.  
  473.         pCurSrc++;
  474.         pCurDest++;
  475.     }
  476.  
  477.     // it is the same decl if reached the end at the same time on both decls
  478.     return ((pCurSrc->Stream == 0xff) && (pCurDest->Stream == 0xff));
  479. }
  480.  
  481. inline void CopyDecls(D3DVERTEXELEMENT9 *pDest, CONST D3DVERTEXELEMENT9 *pSrc)
  482. {
  483.     while (pSrc->Stream != 0xff)
  484.     {
  485.         memcpy(pDest, pSrc, sizeof(D3DVERTEXELEMENT9));
  486.  
  487.         pSrc++;
  488.         pDest++;
  489.     }
  490.     memcpy(pDest, pSrc, sizeof(D3DVERTEXELEMENT9));
  491. }
  492.  
  493. const UINT x_cTypeSizes = D3DDECLTYPE_FLOAT16_4;
  494.  
  495. const BYTE x_rgcbTypeSizes[] = 
  496. {  
  497.     4, // D3DDECLTYPE_FLOAT1,        // 1D float expanded to (value, 0., 0., 1.)
  498.     8, // D3DDECLTYPE_FLOAT2,        // 2D float expanded to (value, value, 0., 1.)
  499.     12, // D3DDECLTYPE_FLOAT3,       / 3D float expanded to (value, value, value, 1.)
  500.     16, // D3DDECLTYPE_FLOAT4,       / 4D float
  501.     4, // D3DDECLTYPE_D3DCOLOR,      // 4D packed unsigned bytes mapped to 0. to 1. range
  502.     //                      // Input is in D3DCOLOR format (ARGB) expanded to (R, G, B, A)
  503.     4, // D3DDECLTYPE_UBYTE4,        // 4D unsigned byte
  504.     4, // D3DDECLTYPE_SHORT2,        // 2D signed short expanded to (value, value, 0., 1.)
  505.     8, // D3DDECLTYPE_SHORT4         // 4D signed short
  506.  
  507.     4, // D3DDECLTYPE_UBYTE4N,       // Each of 4 bytes is normalized by dividing to 255.0
  508.     4, // D3DDECLTYPE_SHORT2N,       // 2D signed short normalized (v[0]/32767.0,v[1]/32767.0,0,1)
  509.     8, // D3DDECLTYPE_SHORT4N,       // 4D signed short normalized (v[0]/32767.0,v[1]/32767.0,v[2]/32767.0,v[3]/32767.0)
  510.     4, // D3DDECLTYPE_USHORT2N,      // 2D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,0,1)
  511.     8, // D3DDECLTYPE_USHORT4N,      // 4D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,v[2]/65535.0,v[3]/65535.0)
  512.     4, // D3DDECLTYPE_UDEC3,         // 3D unsigned 10 10 10 format expanded to (value, value, value, 1)
  513.     4, // D3DDECLTYPE_DEC3N,         // 3D signed 10 10 10 format normalized and expanded to (v[0]/511.0, v[1]/511.0, v[2]/511.0, 1)
  514.     4, // D3DDECLTYPE_FLOAT16_2,     // 2D 16 bit float expanded to (value, value, 0, 1 )
  515.     8, // D3DDECLTYPE_FLOAT16_4,     // 4D 16 bit float 
  516.     0, // D3DDECLTYPE_UNUSED,        // Unused
  517. };
  518.  
  519.  
  520. inline CONST D3DVERTEXELEMENT9* GetDeclElement(CONST D3DVERTEXELEMENT9 *pDecl, BYTE Usage, BYTE UsageIndex)
  521. {
  522.     while (pDecl->Stream != 0xff)
  523.     {
  524.         if ((pDecl->Usage == Usage) && (pDecl->UsageIndex == UsageIndex))
  525.         {
  526.             return pDecl;
  527.         }
  528.  
  529.         pDecl++;
  530.     }
  531.  
  532.     return NULL;
  533. }
  534.  
  535. inline void RemoveDeclElement(BYTE Usage, BYTE UsageIndex, D3DVERTEXELEMENT9 pDecl[MAX_FVF_DECL_SIZE])
  536. {
  537.     LPD3DVERTEXELEMENT9 pCur;
  538.     LPD3DVERTEXELEMENT9 pPrev;
  539.     BYTE cbElementSize;
  540.  
  541.     pCur = pDecl;
  542.     while (pCur->Stream != 0xff)
  543.     {
  544.         if ((pCur->Usage == Usage) && (pCur->UsageIndex == UsageIndex))
  545.         {
  546.             break;
  547.         }
  548.         pCur++;
  549.     }
  550.  
  551.     //. if we found one to remove, then remove it
  552.     if (pCur->Stream != 0xff)
  553.     {
  554.         cbElementSize = x_rgcbTypeSizes[pCur->Type];;
  555.  
  556.         pPrev = pCur;
  557.         pCur++;
  558.         while (pCur->Stream != 0xff)
  559.         {
  560.             memcpy(pPrev, pCur, sizeof(D3DVERTEXELEMENT9));
  561.  
  562.             pPrev->Offset -= cbElementSize;
  563.  
  564.             pPrev++;
  565.             pCur++;
  566.         }
  567.  
  568.         // copy the end of stream down one
  569.         memcpy(pPrev, pCur, sizeof(D3DVERTEXELEMENT9));
  570.     }
  571.  
  572. }
  573.  
  574. // NOTE: size checking of array should happen OUTSIDE this function!
  575. inline void AppendDeclElement(CONST D3DVERTEXELEMENT9 *pNew, D3DVERTEXELEMENT9 pDecl[MAX_FVF_DECL_SIZE])
  576. {
  577.     LPD3DVERTEXELEMENT9 pCur;
  578.     BYTE cbOffset;
  579.     BYTE cbNewOffset;
  580.     D3DVERTEXELEMENT9   TempElement1;
  581.     D3DVERTEXELEMENT9   TempElement2;
  582.     UINT iCur;
  583.  
  584.     pCur = pDecl;
  585.     cbOffset = 0;
  586.     while ((pCur->Stream != 0xff))
  587.     {
  588.         cbOffset += x_rgcbTypeSizes[pCur->Type];
  589.  
  590.         pCur++;
  591.     }
  592.     
  593.     // NOTE: size checking of array should happen OUTSIDE this function!
  594.     GXASSERT(pCur - pDecl + 1 < MAX_FVF_DECL_SIZE);
  595.  
  596.     // move the end of the stream down one
  597.     memcpy(pCur+1, pCur, sizeof(D3DVERTEXELEMENT9));
  598.  
  599.     // copy the new element in and update the offset
  600.     memcpy(pCur, pNew, sizeof(D3DVERTEXELEMENT9));
  601.     pCur->Offset = cbOffset;
  602. }
  603.  
  604. // NOTE: size checking of array should happen OUTSIDE this function!
  605. inline void InsertDeclElement(UINT iInsertBefore, CONST D3DVERTEXELEMENT9 *pNew, D3DVERTEXELEMENT9 pDecl[MAX_FVF_DECL_SIZE])
  606. {
  607.     LPD3DVERTEXELEMENT9 pCur;
  608.     BYTE cbOffset;
  609.     BYTE cbNewOffset;
  610.     D3DVERTEXELEMENT9   TempElement1;
  611.     D3DVERTEXELEMENT9   TempElement2;
  612.     UINT iCur;
  613.  
  614.     pCur = pDecl;
  615.     cbOffset = 0;
  616.     iCur = 0;
  617.     while ((pCur->Stream != 0xff) && (iCur < iInsertBefore))
  618.     {
  619.         cbOffset += x_rgcbTypeSizes[pCur->Type];
  620.  
  621.         pCur++;
  622.         iCur++;
  623.     }
  624.  
  625.     // NOTE: size checking of array should happen OUTSIDE this function!
  626.     GXASSERT(pCur - pDecl + 1 < MAX_FVF_DECL_SIZE);
  627.  
  628.     // if we hit the end, just append
  629.     if (pCur->Stream == 0xff)
  630.     {
  631.         // move the end of the stream down one
  632.         memcpy(pCur+1, pCur, sizeof(D3DVERTEXELEMENT9));
  633.  
  634.         // copy the new element in and update the offset
  635.         memcpy(pCur, pNew, sizeof(D3DVERTEXELEMENT9));
  636.         pCur->Offset = cbOffset;
  637.  
  638.     }
  639.     else  // insert in the middle
  640.     {
  641.         // save off the offset for the new decl
  642.         cbNewOffset = cbOffset;
  643.  
  644.         // calculate the offset for the first element shifted up
  645.         cbOffset += x_rgcbTypeSizes[pNew->Type];
  646.  
  647.         // save off the first item to move, data so that we can copy the new element in
  648.         memcpy(&TempElement1, pCur, sizeof(D3DVERTEXELEMENT9));
  649.  
  650.         // copy the new element in
  651.         memcpy(pCur, pNew, sizeof(D3DVERTEXELEMENT9));
  652.         pCur->Offset = cbNewOffset;
  653.  
  654.         // advance pCur one because we effectively did an iteration of the loop adding the new element
  655.         pCur++;
  656.  
  657.         while (pCur->Stream != 0xff)
  658.         {
  659.             // save off the current element
  660.             memcpy(&TempElement2, pCur, sizeof(D3DVERTEXELEMENT9));
  661.  
  662.             // update the current element with the previous's value which was stored in TempElement1
  663.             memcpy(pCur, &TempElement1, sizeof(D3DVERTEXELEMENT9));
  664.  
  665.             // move the current element's value into TempElement1 for the next iteration
  666.             memcpy(&TempElement1, &TempElement2, sizeof(D3DVERTEXELEMENT9));
  667.  
  668.             pCur->Offset = cbOffset;
  669.             cbOffset += x_rgcbTypeSizes[pCur->Type];
  670.  
  671.             pCur++;
  672.         }
  673.  
  674.     // now we exited one element, need to move the end back one and copy in the last element
  675.         // move the end element back one
  676.         memcpy(pCur + 1, pCur, sizeof(D3DVERTEXELEMENT9));
  677.  
  678.         // copy the prev element's data out of the temp and into the last element
  679.         memcpy(pCur, &TempElement1, sizeof(D3DVERTEXELEMENT9));
  680.         pCur->Offset = cbOffset;
  681.     }
  682. }
  683.  
  684. // this function always adds the weights after the first element.  It DOESN'T matter if that is position or not,
  685. //   but if it is, then it will tend to still be able to generate an FVF
  686. inline HRESULT AddWeights(UINT cWeights, BOOL bIndices, D3DVERTEXELEMENT9 pDecl[MAX_FVF_DECL_SIZE])
  687. {
  688.     UINT cElements;
  689.     D3DVERTEXELEMENT9 Element;
  690.  
  691.     // remove any weights already present (makes adding them easier)
  692.     RemoveDeclElement(D3DDECLUSAGE_BLENDWEIGHT, 0, pDecl);
  693.     RemoveDeclElement(D3DDECLUSAGE_BLENDINDICES, 0, pDecl);
  694.  
  695.     // check the length of the new decl before trying to create it
  696.     cElements = D3DXGetDeclLength(pDecl);
  697.     if (cElements + (bIndices ? 1 : 0) + (cWeights ? 1 : 0) >= MAX_FVF_DECL_SIZE)
  698.     {
  699.         DPF(0, "AddWeightsVertexElements:  Cannot add weight vertex elements.  Too many vertex elements");
  700.         return D3DERR_INVALIDCALL;
  701.     }
  702.  
  703.     // first insert the indices (otherwise we would need to do it variable based on whether weights are present or not
  704.     if (bIndices)
  705.     {
  706.         Element.Stream = 0;
  707.         Element.Method = D3DDECLMETHOD_DEFAULT;
  708.         Element.Usage = D3DDECLUSAGE_BLENDINDICES;
  709.         Element.UsageIndex = 0;
  710.         Element.Type = D3DDECLTYPE_UBYTE4;
  711.         
  712.         InsertDeclElement(1, &Element, pDecl);
  713.     }
  714.  
  715.     // now add the weights
  716.     if (cWeights)
  717.     {
  718.         Element.Stream = 0;
  719.         Element.Method = D3DDECLMETHOD_DEFAULT;
  720.         Element.Usage = D3DDECLUSAGE_BLENDWEIGHT;
  721.         Element.UsageIndex = 0;
  722.         Element.Type = D3DDECLTYPE_FLOAT1 + (cWeights - 1);
  723.         
  724.         InsertDeclElement(1, &Element, pDecl);
  725.     }
  726.  
  727.     return S_OK;
  728. }
  729.  
  730.  
  731.  
  732. #endif // __CRACKDECL_H__